Vector engine for OpenSearch Service ServerlessをCloudFormationで実装してみた #AWSreInvent
こんにちは、つくぼし(tsukuboshi0755)です!
re:Invent 2023でVector engine for OpenSearch Service ServerlessがGAになりました。
このサービスとBedrockのKnowledge baseを組み合わせる事で、RAGシステムを作成できるようになります。
今回はVector engine for OpenSearch Service ServerlessをCloudFormationで構築し、利用する方法を紹介します!
テンプレート
今回は以下のテンプレートをベースに。コレクションの種類をベクトル検索に変更し作成していきます。
全体のコードは以下の通りです。
CloudFormationコード
AWSTemplateFormatVersion: '2010-09-09' Description: Vector engine for OpenSearch Service Serverless Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Parameters: - SysName - Env - CollectionStandbyReplicas - AossDataAccessPrincipalArn Parameters: SysName: Type: String Default: 'cm' Description: 'System name for this stack.' Env: Type: String Default: 'dev' Description: 'Environment for this stack.' AllowedValues: - 'prd' - 'stg' - 'dev' CollectionStandbyReplicas: Type: String Default: 'DISABLED' Description: 'DISABLED is suitable for production environments. ENABLED is suitable for development environments.' AllowedValues: - 'DISABLED' - 'ENABLED' AossDataAccessPrincipalArn: Type: String Default: 'arn:aws:iam::123456789012:user/aoss-data-access-user' Description: 'The ARN of the IAM user or role that has access to the data in the collection.' Resources: AossCollection: Type: 'AWS::OpenSearchServerless::Collection' Properties: Name: !Sub '${SysName}-${Env}-collection' Type: VECTORSEARCH StandbyReplicas: !Ref CollectionStandbyReplicas DependsOn: AossEncryptionPolicy AossEncryptionPolicy: Type: 'AWS::OpenSearchServerless::SecurityPolicy' Properties: Name: !Sub '${SysName}-${Env}-encryption-policy' Type: encryption Policy: !Sub >- { "Rules":[ { "Resource":[ "collection/${SysName}-${Env}-collection" ], "ResourceType": "collection" } ], "AWSOwnedKey": true } AossNetworkPolicy: Type: 'AWS::OpenSearchServerless::SecurityPolicy' Properties: Name: !Sub '${SysName}-${Env}-network-policy' Type: network Policy: !Sub >- [ { "Rules":[ { "Resource":[ "collection/${SysName}-${Env}-collection" ], "ResourceType": "dashboard" }, { "Resource":[ "collection/${SysName}-${Env}-collection" ], "ResourceType": "collection" } ], "AllowFromPublic": true } ] AossDataAccessPolicy: Type: 'AWS::OpenSearchServerless::AccessPolicy' Properties: Name: !Sub '${SysName}-${Env}-data-access-policy' Type: data Policy: !Sub >- [ { "Rules":[ { "Resource":[ "collection/${SysName}-${Env}-collection" ], "Permission":[ "aoss:CreateCollectionItems", "aoss:UpdateCollectionItems", "aoss:DescribeCollectionItems" ], "ResourceType": "collection" }, { "Resource":[ "index/${SysName}-${Env}-collection/*" ], "Permission":[ "aoss:CreateIndex", "aoss:UpdateIndex", "aoss:DescribeIndex", "aoss:ReadDocument", "aoss:WriteDocument" ], "ResourceType": "index" } ], "Principal":[ "${AossDataAccessPrincipalArn}" ], "Description": "" } ] Outputs: Endpoint: Value: !GetAtt AossCollection.CollectionEndpoint
以下より、本テンプレートで作成される各リソースについて説明します。
コレクション
AossCollection: Type: 'AWS::OpenSearchServerless::Collection' Properties: Name: !Sub '${SysName}-${Env}-collection' Type: VECTORSEARCH StandbyReplicas: !Ref CollectionStandbyReplicas DependsOn: AossEncryptionPolicy
OpenSearch Serverlessのデータベースであるコレクションを作成します。
今回はベクトル検索を行うため、Type
をVECTORSEARCH
に指定します。
また、StandbyReplicas
はDISABLED
にする事で、開発/テストオプションが有効になり、スタンバイレプリカの無効化によりコストを削減できます。
なお本番環境等で可用性を重視する場合は、ENABLED
にしスタンバイレプリカを有効化する事を推奨します。
暗号化ポリシー
AossEncryptionPolicy: Type: 'AWS::OpenSearchServerless::SecurityPolicy' Properties: Name: !Sub '${SysName}-${Env}-encryption-policy' Type: encryption Policy: !Sub >- { "Rules":[ { "Resource":[ "collection/${SysName}-${Env}-collection" ], "ResourceType": "collection" } ], "AWSOwnedKey": true }
OpenSearch Serverlessのデータを暗号化するためポリシーを作成します。
今回はAWSが所有するKMSキーを使用するため、AWSOwnedKey
をtrue
に指定します。
なお代わりに自身が所有するKMSキーを使用したい場合は、以下の通りAWSOwnedKey
をfalse
にし、KmsARN
にKMSキーのARNを指定してください。
AossEncryptionPolicy: Type: 'AWS::OpenSearchServerless::SecurityPolicy' Properties: Name: !Sub '${SysName}-${Env}-encryption-policy' Type: encryption Policy: !Sub >- { "Rules":[ { "Resource":[ "collection/${SysName}-${Env}-collection" ], "ResourceType": "collection" } ], "AWSOwnedKey": false, "KmsARN": "<KMSキーのARN>" }
ネットワークポリシー
AossNetworkPolicy: Type: 'AWS::OpenSearchServerless::SecurityPolicy' Properties: Name: !Sub '${SysName}-${Env}-network-policy' Type: network Policy: !Sub >- [ { "Rules":[ { "Resource":[ "collection/${SysName}-${Env}-collection" ], "ResourceType": "dashboard" }, { "Resource":[ "collection/${SysName}-${Env}-collection" ], "ResourceType": "collection" } ], "AllowFromPublic": true } ]
OpenSearch Serverlessをネットワークからアクセスするためのポリシーを作成します。
今回はパブリックアクセスを使用するため、AllowFromPublic
をtrue
に指定します。
なおVPCアクセスを使用したい場合は、以下の通りAllowFromPublic
をfalse
にし、SourceVPCEs
にVPCのインタフェースエンドポイントIDを指定してください。
AossNetworkPolicy: Type: 'AWS::OpenSearchServerless::SecurityPolicy' Properties: Name: !Sub '${SysName}-${Env}-network-policy' Type: network Policy: !Sub >- [ { "Rules":[ { "Resource":[ "collection/${SysName}-${Env}-collection" ], "ResourceType": "dashboard" }, { "Resource":[ "collection/${SysName}-${Env}-collection" ], "ResourceType": "collection" } ], "AllowFromPublic": false, "SourceVPCEs":[ "<OpenSearch ServerlessのインタフェースエンドポイントID>" ] } ]
データアクセスポリシー
AossDataAccessPolicy: Type: 'AWS::OpenSearchServerless::AccessPolicy' Properties: Name: !Sub '${SysName}-${Env}-data-access-policy' Type: data Policy: !Sub >- [ { "Rules":[ { "Resource":[ "collection/${SysName}-${Env}-collection" ], "Permission":[ "aoss:CreateCollectionItems", "aoss:UpdateCollectionItems", "aoss:DescribeCollectionItems" ], "ResourceType": "collection" }, { "Resource":[ "index/${SysName}-${Env}-collection/*" ], "Permission":[ "aoss:CreateIndex", "aoss:UpdateIndex", "aoss:DescribeIndex", "aoss:ReadDocument", "aoss:WriteDocument" ], "ResourceType": "index" } ], "Principal":[ "${AossDataAccessPrincipalArn}" ], "Description": "" } ]
OpenSearch Serverlessのデータにアクセスするためのポリシーを作成します。
今回はPrincipal
にあるAossDataAccessPrincipalArn
に対して任意のIAMユーザまたはIAMロールのARNを指定し、データの作成/変更/閲覧をできるように設定します。
検索の確認
上記のテンプレートをデプロイする事で、OpenSearch Serverlessを用いて正常にデータをベクトル検索できるか確認します。
CloudFormationスタックのデプロイ
今回は以下のパラメータで、CloudFormationスタックをデプロイします。
AossDataAccessPrincipalArn
には、今回作成するコレクションにアクセスするIAMユーザまたはIAMロールのARNを指定してください。
スタックの作成が完了すると、以下の通りOpenSearch ServerlessのエンドポイントURLが出力されます。
このURLは後で使用するのでメモしておいてください。
データアップロード/ベクトル検索
今回の確認で使用するデータ及び確認手順としては、以下の公式ドキュメントを参照します。
上記の公式ドキュメントに記載されている検索を実施するには、Postman
やawscurl
といったHTTPツールを使用する必要があります。
今回はawscurl
を導入し、使用する場合の手順を紹介します。
代わりにPostman
を使用したい場合は、以下の記事をご参照ください。
また実行環境にはCloudShellを利用します。
初めにpip3コマンドでawscurl
をインストールします。
$ pip3 install awscurl
次に、以下のコマンドを実行し、先ほどメモしたOpenSearch ServerlessのエンドポイントURLを設定します。
$ AOSS_ENDPOINT=<OpenSearch ServerlessのエンドポイントURL>
それではOpenSearch Serverlessのインデックスを、以下のコマンドで作成しましょう。
$ awscurl --service aoss --region ${AWS_REGION} \ -X PUT \ -d '{"settings": {"index.knn": true}, "mappings": {"properties": {"housing-vector": {"type": "knn_vector", "dimension": 3}, "title": {"type": "text"}, "price": {"type": "long"}, "location": {"type": "geo_point"}}}}' \ ${AOSS_ENDPOINT}/housing-index | jq -r .
インデックス作成が問題なく完了すると、以下のようなレスポンスが返ります。
# レスポンス例 { "acknowledged": true, "shards_acknowledged": true, "index": "housing-index" }
続いて作成したOpenSearch Serverlessのインデックスに対して、以下のコマンドでサンプルドキュメントをアップロードしましょう。
$ awscurl --service aoss --region ${AWS_REGION} \ -X POST \ -d '{"housing-vector":[10, 20, 30], "title": "2 bedroom in downtown Seattle", "price": "2800", "location": "47.71, 122.00"}' \ ${AOSS_ENDPOINT}/housing-index/_doc | jq -r .
ドキュメントアップロードが問題なく完了すると、以下のようなレスポンスが返ります。
# レスポンス例 { "_index": "housing-index", "_id": "1%3A0%3AqgCYL4wBz5Soks5im65k", "_version": 1, "result": "created", "_shards": { "total": 0, "successful": 0, "failed": 0 }, "_seq_no": 0, "_primary_term": 0 }
最後に作成したOpenSearch Serverlessのインデックスに対して、以下のコマンドで特定のプロパティに類似したデータをベクトル検索しましょう。
$ awscurl --service aoss --region ${AWS_REGION} \ -X GET \ -d '{"size": 5, "query": {"knn": {"housing-vector": {"vector":[10, 20, 30], "k": 5}}}}' \ ${AOSS_ENDPOINT}/housing-index/_search | jq -r .
正しく手順が実施できていれば、以下のように先ほどアップロードしたデータがベクトル検索でヒットする事が分かります。
# レスポンス例 { "took": 73, "timed_out": false, "_shards": { "total": 0, "successful": 0, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 1, "relation": "eq" }, "max_score": 1.0, "hits":[ { "_index": "housing-index", "_id": "1%3A0%3AAHx3Q4wBwuFCx3ceGjz8", "_score": 1.0, "_source": { "housing-vector":[ 10, 20, 30 ], "title": "2 bedroom in downtown Seattle", "price": "2800", "location": "47.71, 122.00" } } ] } }
上記の手順を踏む事で、ベクトル検索が正常に実施できる事を確認できました!
なお、アクセスキー及びシークレットアクセスキーを使用する事で、CloudShellにプリインストールされているcurl
でもベクトル検索が可能です。
詳細は以下記事をご参照ください。
最後に
今回はVector engine for OpenSearch Service ServerlessをCloudFormationで構築し、利用する方法を紹介しました。
今後BedrockのKnowledge baseを利用する場合、こちらのサービスを合わせて構築する機会が増えていくのではないでしょうか。
そのような場合に、この記事が少しでもお役に立てれば幸いです。
以上、つくぼし(tsukuboshi0755)でした!